#include "Bishop.h"

#include "SquareValueBoard.h"

using namespace Rorn::Chess::TheCorruptRook;

Bishop::Bishop(void)
{
}

Bishop::~Bishop(void)
{
}

/*static*/ double Bishop::CalculateScore(const Position& position, Player::Type player, const Square& square)
{
	double materialScore = 3.3;

	std::vector<Square> visibleAttackSquares;
	GetVisibleAttackSquares(position, player, square, visibleAttackSquares);
	double visibilityScore = 0;
	for(std::vector<Square>::const_iterator sqaureIter = visibleAttackSquares.begin() ; sqaureIter != visibleAttackSquares.end() ; ++sqaureIter)
		visibilityScore += SquareValueBoard::GetSquareValue(*sqaureIter);

	return materialScore + visibilityScore;
}

/*static*/ void Bishop::GetLegalMoves(const Position& position, Player::Type player, const Square& startSquare, std::vector<MoveTreeNode>& legalMoves, int depth)
{
	// NE
	int squaresNorth = 1;
	int squaresEast = 1;
	bool keepGoing = true;
	while(keepGoing)
	{
		Square potentialSquare(startSquare.GetRank() + squaresNorth, startSquare.GetFile() + squaresEast);

		keepGoing = false;
		if( Square::IsOnBoard(potentialSquare) )
		{
			if(position.GetPiece(player, potentialSquare) == 0)
			{
				legalMoves.emplace_back(MoveTreeNode(position, Player::GetOpposite(player), depth, startSquare, potentialSquare));
				++squaresNorth;
				++squaresEast;
				keepGoing = true;
			}
			else if(position.GetPiece(player, potentialSquare) < 0)
			{
				legalMoves.emplace_back(MoveTreeNode(position, Player::GetOpposite(player), depth, startSquare, potentialSquare));
			}
		}
	}
	
	// SE
	squaresNorth = -1;
	squaresEast = 1;
	keepGoing = true;
	while(keepGoing)
	{
		Square potentialSquare(startSquare.GetRank() + squaresNorth, startSquare.GetFile() + squaresEast);

		keepGoing = false;
		if( Square::IsOnBoard(potentialSquare) )
		{
			if(position.GetPiece(player, potentialSquare) == 0)
			{
				legalMoves.emplace_back(MoveTreeNode(position, Player::GetOpposite(player), depth, startSquare, potentialSquare));
				--squaresNorth;
				++squaresEast;
				keepGoing = true;
			}
			else if(position.GetPiece(player, potentialSquare) < 0)
			{
				legalMoves.emplace_back(MoveTreeNode(position, Player::GetOpposite(player), depth, startSquare, potentialSquare));
			}
		}
	}

	// SW
	squaresNorth = -1;
	squaresEast = -1;
	keepGoing = true;
	while(keepGoing)
	{
		Square potentialSquare(startSquare.GetRank() + squaresNorth, startSquare.GetFile() + squaresEast);

		keepGoing = false;
		if( Square::IsOnBoard(potentialSquare) )
		{
			if(position.GetPiece(player, potentialSquare) == 0)
			{
				legalMoves.emplace_back(MoveTreeNode(position, Player::GetOpposite(player), depth, startSquare, potentialSquare));
				--squaresNorth;
				--squaresEast;
				keepGoing = true;
			}
			else if(position.GetPiece(player, potentialSquare) < 0)
			{
				legalMoves.emplace_back(MoveTreeNode(position, Player::GetOpposite(player), depth, startSquare, potentialSquare));
			}
		}
	}

	// NW
	squaresNorth = 1;
	squaresEast = -1;
	while(keepGoing)
	{
		Square potentialSquare(startSquare.GetRank() + squaresNorth, startSquare.GetFile() + squaresEast);

		keepGoing = false;
		if( Square::IsOnBoard(potentialSquare) )
		{
			if(position.GetPiece(player, potentialSquare) == 0)
			{
				legalMoves.emplace_back(MoveTreeNode(position, Player::GetOpposite(player), depth, startSquare, potentialSquare));
				++squaresNorth;
				--squaresEast;
				keepGoing = true;
			}
			else if(position.GetPiece(player, potentialSquare) < 0)
			{
				legalMoves.emplace_back(MoveTreeNode(position, Player::GetOpposite(player), depth, startSquare, potentialSquare));
			}
		}
	}
}

/*static*/ void Bishop::GetVisibleAttackSquares(const Position& position, Player::Type player, const Square& square, std::vector<Square>& visibleAttackSquares)
{
	// NE
	int squaresNorth = 1;
	int squaresEast = 1;
	bool keepGoing = true;
	while(keepGoing)
	{
		Square potentialSquare(square.GetRank() + squaresNorth, square.GetFile() + squaresEast);

		keepGoing = false;
		if( Square::IsOnBoard(potentialSquare) )
		{
			if(position.GetPiece(player, potentialSquare) == 0)
			{
				visibleAttackSquares.push_back(potentialSquare);
				++squaresNorth;
				++squaresEast;
				keepGoing = true;
			}
			else if(position.GetPiece(player, potentialSquare) < 0)
			{
				visibleAttackSquares.push_back(potentialSquare);
			}
		}
	}

	// SE
	squaresNorth = -1;
	squaresEast = 1;
	keepGoing = true;
	while(keepGoing)
	{
		Square potentialSquare(square.GetRank() + squaresNorth, square.GetFile() + squaresEast);

		keepGoing = false;
		if( Square::IsOnBoard(potentialSquare) )
		{
			if(position.GetPiece(player, potentialSquare) == 0)
			{
				visibleAttackSquares.push_back(potentialSquare);
				--squaresNorth;
				++squaresEast;
				keepGoing = true;
			}
			else if(position.GetPiece(player, potentialSquare) < 0)
			{
				visibleAttackSquares.push_back(potentialSquare);
			}
		}
	}

	// SW
	squaresNorth = -1;
	squaresEast = -1;
	keepGoing = true;
	while(keepGoing)
	{
		Square potentialSquare(square.GetRank() + squaresNorth, square.GetFile() + squaresEast);

		keepGoing = false;
		if( Square::IsOnBoard(potentialSquare) )
		{
			if(position.GetPiece(player, potentialSquare) == 0)
			{
				visibleAttackSquares.push_back(potentialSquare);
				--squaresNorth;
				--squaresEast;
				keepGoing = true;
			}
			else if(position.GetPiece(player, potentialSquare) < 0)
			{
				visibleAttackSquares.push_back(potentialSquare);
			}
		}
	}

	// NW
	squaresNorth = 1;
	squaresEast = -1;
	while(keepGoing)
	{
		Square potentialSquare(square.GetRank() + squaresNorth, square.GetFile() + squaresEast);

		keepGoing = false;
		if( Square::IsOnBoard(potentialSquare) )
		{
			if(position.GetPiece(player, potentialSquare) == 0)
			{
				visibleAttackSquares.push_back(potentialSquare);
				++squaresNorth;
				--squaresEast;
				keepGoing = true;
			}
			else if(position.GetPiece(player, potentialSquare) < 0)
			{
				visibleAttackSquares.push_back(potentialSquare);
			}
		}
	}
}